#ifndef MODULE_HPP_
#define MODULE_HPP_

/*******************************************************************************
 ** Name: module.hpp                                                       **
 ** Description:                                                              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  Redistribution and use in source and binary forms, with or without       **
 **  modification, are permitted provided that the following conditions are   **
 **  met:                                                                     **
 **                                                                           **
 **  * Redistributions of source code must retain the above copyright notice, **
 **    this list of conditions and the following disclaimer.                  **
 **  * Redistributions in binary form must reproduce the above copyright      **
 **    notice, this list of conditions and the following disclaimer in the    **
 **    documentation and/or other materials provided with the distribution.   **
 **                                                                           **
 **  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS      **
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED **
 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           **
 ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT        **
 ** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    **
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  **
 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR    **
 ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    **
 ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      **
 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        **
 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              **
 **                                                                           **
 ******************************************************************************/
// Created on April 4, 2010, 10:03 AM
// Modified $Date: 2011-09-18 21:48:59 +0000 (Sun, 18 Sep 2011) $ by $Author: gian.james $
#define module_hpp_ID   "$Id: module.hpp 145 2011-09-18 21:48:59Z gian.james $"

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <list>

#define DEFAULT_MODULE_DIR	"data/modules/"

// Use the next two defines if/when you need to create or instantiate data or
// do things before anything else is done/created.  Thing of them as C constructors.
#define EXPORT_INIT_BEGIN 	\
	extern "C" { void _init() {
#define EXPORT_INIT_END		\
	} }

// Use the next two defines if/when you need to do anything after everything
// is torn down but befor exit.
#define EXPORT_FINI_BEGIN	\
	extern "C" { void _fini() {
#define EXPORT_FINI_END		\
	} }

// Every module must have this called one and only one time.
// Taken from KLibLoader, taken from tnmud.  it gives the main program access
// to module's factory class, which is then used to comm w/ the module
#define EXPORT_MODULE( libname, moduleclass ) \
	extern "C" { void * init_ ## libname() { return new moduleclass; } }

enum ModError { Unknown, NonExist, AlreadyLoaded, NotModule, NoEntry };

class ModuleBase
{
public:

};

class Module
{
public:
	Module(const std::string & s);

	const std::string & Name() const { return name; }
	void		Desc(const std::string & d) { desc = d; }
	const std::string & Desc() const { return desc; }
	const std::string & Location() const { return loc; }
	void		Location(const std::string & l) { loc = l; }
	const std::string & Version() const { return ver; }
	const std::string & Author() const { return author; }
	const std::string & Entry() const { return entry; }
	const bool	InitSupplied() const { return bInit; }
	const bool	FiniSupplied() const { return bFini; }
	void		InitSupplied(const bool b) { bInit = b; }
	void		FiniSupplied(const bool b) { bFini = b; }
	void		Version(const std::string & v) { ver = v; }
	void		Author(const std::string & a) { author = a; }
	void		Entry(const std::string & e) { entry = e; }
	void *		Library(void * l = 0) { if (l) lib = l; return lib; }
	const bool	Loaded() const { return loaded; }
	void		Loaded(const bool l) { loaded = l; }
	ModuleBase *GetModule() { return mod; }
	void		SetModule(ModuleBase * m) { mod = m; }

	std::string	UUID2String() { return boost::uuids::to_string(oid); }
	boost::uuids::uuid	OID() const { return oid; }

protected:
	boost::uuids::uuid	oid;	// generates a new UUID every load
	std::string			name;
	std::string			desc;
	std::string			loc;	// it's file location including file name
	std::string			ver;
	std::string			author;
	std::string			entry;
	ModuleBase *		mod;

	bool	bInit, bFini;
	bool	loaded;
	void *	lib;
};

bool operator == (const Module & m1, const Module m2) {
	return m1.OID() == m2.OID();
}

class ModuleManager
{
public:
	ModuleManager();
	~ModuleManager();

	int		Init();
	int		LoadModules();
	int		LoadModule(const std::string & m);
	bool	UnloadModule(const std::string & m);
	void	Print() const ;

private:
	std::list<Module *>	modules;
};



#endif /* MODULE_HPP_ */
